home *** CD-ROM | disk | FTP | other *** search
/ Symantec Visual Cafe for Java 2.5 / symantec-visual-cafe-2.5-database-dev-edition.iso / Visual Cafe Pro v1.0 / SOURCE.BIN / ImageListBox.java < prev    next >
Encoding:
Java Source  |  1997-06-19  |  75.9 KB  |  2,500 lines

  1. package symantec.itools.awt;
  2.  
  3.  
  4. import java.awt.Panel;
  5. import java.awt.Dimension;
  6. import java.awt.Component;
  7. import java.awt.Image;
  8. import java.awt.Graphics;
  9. import java.awt.Event;
  10. import java.awt.Scrollbar;
  11. import java.awt.Font;
  12. import java.awt.FontMetrics;
  13. import java.awt.Color;
  14. import java.awt.Rectangle;
  15. import java.util.Vector;
  16. import java.awt.image.MemoryImageSource;
  17.  
  18.  
  19. /**
  20.  * Creates a box containing a list of images.
  21.  * <p>
  22.  * Use a ImageListBox to display a set of images that the user can select. 
  23.  * The user cannot type a selection in a list box.
  24.  * <p>
  25.  * @version 1.0, Nov 26, 1996
  26.  * @author Symantec
  27.  */
  28.  
  29. //     03/02/97    RKM    In ctor, make certain bar size is correct for Macs
  30. //     03/21/97    RKM    Removed repaint hack from paint
  31.  
  32. public class ImageListBox
  33.     extends Panel
  34. {
  35.     //--------------------------------------------------
  36.     // constants
  37.     //--------------------------------------------------
  38.  
  39.     /**
  40.      * Defines the Event ID for when the image portion of a list item
  41.      * is selected.
  42.      */
  43.     public static final int EVT_IMAGE_SELECT = 0x4004;
  44.  
  45.     /**
  46.      * Defines the "regular" border style.
  47.      * @see #setBorderType
  48.      * @see #getBorderType
  49.      */
  50.     public static final int BORDER_REGULAR = 0;
  51.  
  52.     /**
  53.      * Defines "no border" style.
  54.      * @see #setBorderType
  55.      * @see #getBorderType
  56.      */
  57.     public static final int BORDER_NONE = 1;
  58.  
  59.     /**
  60.      * Defines the width of displayed images, in pixels.
  61.      */
  62.     public static final int IMAGE_WIDTH = 19;
  63.  
  64.  
  65.     private final int LINE_SLOP = 6;
  66.  
  67.  
  68.     //--------------------------------------------------
  69.     // class variables
  70.     //--------------------------------------------------
  71.  
  72.  
  73.     //--------------------------------------------------
  74.     // member variables
  75.     //--------------------------------------------------
  76.  
  77.     /**
  78.      * Zero-relative index of the item displayed in the top row.
  79.      */
  80.     protected int   nTopRow = 0;
  81.     /**
  82.      * Width of the list content portion of this component, in pixels.
  83.      */
  84.     protected int   lWidth = 0;
  85.     /**
  86.      * Height of a single list cell, in pixels.
  87.      */
  88.     protected int   cellHt = 0;
  89.     /**
  90.      * Top margin before the contents of the first list item, in pixels.
  91.      */
  92.     protected int   yAdj = 6;
  93.     /**
  94.      * Width of the left and right borders combined, in pixels.
  95.      */
  96.     protected int       borderWidth = 4;
  97.     /**
  98.      * Width of the left or right border, in pixels.
  99.      */
  100.     protected int       halfBorderWidth = 2;
  101.     private Component ilbParent;
  102.     private String ilbLabel;
  103.     private Image       SelectImage;
  104.     private Scrollbar   VBar = null;
  105.     private Scrollbar   HBar = null;
  106.     private Vector      items;
  107.     private Font        font;
  108.     private FontMetrics fm = null;
  109.     private boolean bAllDirty = true;
  110.     private boolean bMultipleSelections = false;
  111.     private boolean bBlockPaint = false;
  112.     private boolean bVBarVisible = false;
  113.     private boolean bHBarVisible = false;
  114.     private boolean bInternalBlockPaint = false;
  115.     private int     rowsToShow = -1;
  116.     private int     colsToShow = 10;
  117.     private int     visibleRows = -1;
  118.     private int     visibleCols = -1;
  119.     private int     visibleIndex = -1;
  120.     private int     fontHeight;
  121.     private int     fontDescent;
  122.     private int     lastDownModifiers = -1;
  123.     private int     lastSelected = -1;
  124.     private int     lastIndex = -1;
  125.     private int     lastTempIndex = -1;
  126.     private int     countSelected = 0;
  127.     private int     borderType = 0;
  128.     private int     longestLineValue = 0;
  129.     private int     barSize = 15;
  130.     private int     xCoord = 0;
  131.     private long    prevSelectTime = -1;
  132.     private long    prevSelectRow = -1;
  133.     private boolean bOsFlag;
  134.     private boolean bComboMode = false;
  135.     private boolean bCellBorders = false;
  136.     private boolean bAllowShowVBar = true;
  137.     private boolean bAllowShowHBar = true;
  138.     private Color enabledColor = Color.black;
  139.     private Color disabledColor = Color.gray;
  140.     private int fastDownCount = 0;
  141.     private boolean bMouseDrawHandled = false;
  142.     private boolean bDirectNotify = true;
  143.  
  144.  
  145.     //--------------------------------------------------
  146.     // constructors
  147.     //--------------------------------------------------
  148.  
  149.     /**
  150.      * Construct a default ImageListBox.
  151.      * A default ImageListBox has no name label, will show the maximum number of
  152.      * visible rows, and allows single list item selection.
  153.      */
  154.     public ImageListBox()
  155.     {
  156.         this(null, "", -1, false);
  157.     }
  158.  
  159.     /**
  160.      * Construct an ImageListBox with the specified name label.
  161.      * It will show the maximum number of visible rows, and allows single list 
  162.      * item selection.
  163.      * @param label the name label of the list box
  164.      */
  165.     public ImageListBox(String label)
  166.     {
  167.         this(null, label, -1, false);
  168.     }
  169.  
  170.     /**
  171.      * Construct an ImageListBox with the specified name label and
  172.      * conditionally allow multiple selections.
  173.      * It will show the maximum number of visible rows.
  174.      * @param label the name label of the list box
  175.      * @param bMultipleSelections if true then multiple selections are allowed;
  176.      * if false only single item selections are allowed
  177.      */
  178.     public ImageListBox(String label, boolean bMultipleSelections)
  179.     {
  180.         this(null, label, -1, bMultipleSelections);
  181.     }
  182.  
  183.     /**
  184.      * Construct an ImageListBox with the specified name label, the
  185.      * specified number of visible rows,  and conditionally allow multiple
  186.      * list item selection.
  187.      * @param label the name label of the list box
  188.      * @param rows the number of row items to show.  If rows is less than or equal
  189.      * to zero, the maximum possible number of rows will be shown
  190.      * @param bMultipleSelections if true then multiple selections are allowed;
  191.      * if false only single item selections are allowed
  192.      */
  193.     public ImageListBox(String label, int rows, boolean bMultipleSelections)
  194.     {
  195.         this(null, label, rows, bMultipleSelections);
  196.     }
  197.  
  198.     /**
  199.      * Construct an ImageListBox with a specific parent component and the 
  200.      * specified name label. It will show the maximum visible rows and 
  201.      * allowing single list item selection.
  202.      * @param parent the parent of the list box, where all events are sent
  203.      * @param label the name label of the list box
  204.      */
  205.     public ImageListBox(Component parent, String label)
  206.     {
  207.         this(parent, label, -1, false);
  208.     }
  209.  
  210.     /**
  211.      * Construct an ImageListBox.
  212.      * The created ImageListBox will have a specific parent component, 
  213.      * the specified name label, show a specified number of rows and 
  214.      * conditionally allow multiple list item selection.  
  215.      * If the specified parent is null, the
  216.      * parent (for event passing purposes) will be determined at event time.
  217.      * @param parent the parent of the list box, where all events should be sent
  218.      * @param slabel the name label of the list box
  219.      * @param rows the number of items to show.  If rows is less then or equal
  220.      * to zero, the maximum possible number of rows will be shown
  221.      * @param bMultipleSelections if true then multiple selections are allowed;
  222.      * if false only single item selections are allowed
  223.      */
  224.     public ImageListBox(Component parent, String slabel, int rows, boolean bMultipleSelections)
  225.     {
  226.         if (!System.getProperty("os.name").startsWith("S")) // SunOS, Solaris
  227.         {
  228.             bOsFlag = false;
  229.             if (symantec.itools.lang.OS.isMacintosh())
  230.                 barSize = 16;
  231.             else
  232.             barSize = 15;
  233.         }
  234.         else
  235.         {
  236.             bOsFlag = true;
  237.             barSize = 17;
  238.         }
  239.  
  240.         items = new Vector();
  241.  
  242.         ilbParent = parent;
  243.         ilbLabel = slabel;
  244.         rowsToShow = rows;
  245.         this.bMultipleSelections = bMultipleSelections;
  246.  
  247.         // Create select image
  248.         int w = 20;
  249.         int h = 20;
  250.         int pix[] = new int[w * h];
  251.         int index = 0;
  252.         for (int y = 0; y < h; y++)
  253.         {
  254.             for (int x = 0; x < w; x++)
  255.             {
  256.                 pix[index++] = (255 << 24) | 128;
  257.             }
  258.         }
  259.         SelectImage = createImage(new MemoryImageSource(w, h, pix, 0, w));
  260.  
  261.         setLayout(null);
  262.         setBackground(Color.white);
  263.  
  264.         VBar = new Scrollbar();
  265.         VBar.setBackground(Color.lightGray);
  266.         add(VBar);
  267.  
  268.         HBar = new Scrollbar(Scrollbar.HORIZONTAL);
  269.         HBar.setBackground(Color.lightGray);
  270.         add(HBar);
  271.  
  272.         setFont(new Font("Helvetica", java.awt.Font.PLAIN, 12));
  273.      }
  274.  
  275.  
  276.     //--------------------------------------------------
  277.     // accessor methods
  278.     //--------------------------------------------------
  279.  
  280.     /**
  281.      * Sets ImageListBox "ComboBox Mode".
  282.      * This only applies when the ImageListBox is not allowing multiple
  283.      * selections.  "ComboBox Mode" allows the selection point to follow
  284.      * the mouse even when the mouse button is not down.
  285.      * @param cond true for "ComboBox Mode", false for normal list box mode.
  286.      * @see #getComboMode
  287.      */
  288.     public void setComboMode(boolean cond)
  289.     {
  290.         bComboMode = cond;
  291.         yAdj = 6;
  292.         invalidate();
  293.     }
  294.  
  295.     /**
  296.      * Returns the current ImageListBox "ComboBox Mode" setting.
  297.      * @see #setComboMode
  298.      */
  299.     public boolean getComboMode()
  300.     {
  301.         return bComboMode;
  302.     }
  303.  
  304.     /**
  305.      * Sets the number of rows to display in the ImageListBox.
  306.      * @param rows number of rows to display
  307.      * @see #getRowsToShow
  308.      */
  309.     public void setRowsToShow(int rows)
  310.     {
  311.         rowsToShow = rows;
  312.         invalidate();
  313.     }
  314.  
  315.     /**
  316.      * Returns the current number of rows to display value.
  317.      * @see #setRowsToShow
  318.      */
  319.     public int getRowsToShow()
  320.     {
  321.         return rowsToShow;
  322.     }
  323.  
  324.     /**
  325.      * Sets the vertical scrollbar visibility flag.
  326.      * @param cond if true, the vertical scrollbar will be made
  327.      * visible when necessary; if false, the vertical scrollbar
  328.      * will never be made visible
  329.      * @see #getShowVerticalScroll
  330.      */
  331.     public void setShowVerticalScroll(boolean cond)
  332.     {
  333.         if (bAllowShowVBar != cond)
  334.         {
  335.             bAllowShowVBar = cond;
  336.             invalidate();
  337.         }
  338.     }
  339.  
  340.     /**
  341.      * Returns the current vertical scrollbar visibility flag.
  342.      * @see #setShowVerticalScroll
  343.      */
  344.     public boolean getShowVerticalScroll()
  345.     {
  346.         return bAllowShowVBar;
  347.     }
  348.  
  349.     /**
  350.      * Sets the horizontal scrollbar visibility flag.
  351.      * @param cond if true, the horizontal scrollbar will be made
  352.      * visible when necessary; if false, the horizontal scrollbar
  353.      * will never be made visible
  354.      * @see #getShowHorizontalScroll
  355.      */
  356.     public void setShowHorizontalScroll(boolean cond)
  357.     {
  358.         if (bAllowShowHBar != cond)
  359.         {
  360.             bAllowShowHBar = cond;
  361.             invalidate();
  362.         }
  363.     }
  364.  
  365.     /**
  366.      * Returns the current horizontal scrollbar visibility flag.
  367.      * @see #setShowHorizontalScroll
  368.      */
  369.     public boolean getShowHorizontalScroll()
  370.     {
  371.         return bAllowShowHBar;
  372.     }
  373.  
  374.     /**
  375.      * Sets the border type of the ImageListBox.
  376.      * @param type new border type
  377.      * @see #getBorderType
  378.      * @see #BORDER_REGULAR
  379.      * @see #BORDER_NONE
  380.      */
  381.     public void setBorderType(int type)
  382.     {
  383.         borderType = type;
  384.         if (type == BORDER_REGULAR)
  385.         {
  386.             borderWidth = 4;
  387.             halfBorderWidth = 2;
  388.         }
  389.         else
  390.         {
  391.             borderWidth = 0;
  392.             halfBorderWidth = 0;
  393.         }
  394.         invalidate();
  395.     }
  396.  
  397.     /**
  398.      * Returns the current border type of the ImageListBox.
  399.      * @see #setBorderType
  400.      * @see #BORDER_REGULAR
  401.      * @see #BORDER_NONE
  402.      */
  403.     public int getBorderType()
  404.     {
  405.         return borderType;
  406.     }
  407.  
  408.     /**
  409.      * Conditionally show cell borders for a specific index.
  410.      * @param cond true to show the cell borders; false to
  411.      * not show the cell borders
  412.      * @see #setCellBorders
  413.      */
  414.     public void setCellBorder(int index, boolean bOn)
  415.     {
  416.         if (validIndex(index))
  417.         {
  418.             ListItem li = (ListItem) items.elementAt(index);
  419.             if (li.bCellBorder != bOn)
  420.             {
  421.                 li.bCellBorder = bOn;
  422.                 li.bDirty = true;
  423.                 invalidate();
  424.             }
  425.         }
  426.     }
  427.  
  428.     /**
  429.      * Sets the ImageListBox cell border display default, and
  430.      * resets all items to have the border conditionally.
  431.      * @param cond true for "default grid lines on" mode,
  432.      * false for "default grid lines off" mode.
  433.      * @see #setCellBorder
  434.      * @see #getCellBorders
  435.      */
  436.     public void setCellBorders(boolean bOn)
  437.     {
  438.         bCellBorders = bOn;
  439.  
  440.         int s = items.size();
  441.         ListItem li = null;
  442.  
  443.         for (int x = 0; x < s; x++)
  444.         {
  445.             li = (ListItem) items.elementAt(x);
  446.             li.bCellBorder = bOn;
  447.         }
  448.         bAllDirty = true;
  449.         invalidate();
  450.     }
  451.  
  452.     /**
  453.      * Gets the current cell border display mode.
  454.      * @return boolean - true for "default grid lines on" mode,
  455.      * false for "default grid lines off" mode.
  456.      * @see #setCellBorders
  457.      */
  458.     public boolean getCellBorders()
  459.     {
  460.         return bCellBorders;
  461.     }
  462.  
  463.     /**
  464.      * Set the default color for enabled text items.
  465.      * @param color the new default text color
  466.      * @see #getDefaultEnabledTextColor
  467.      */
  468.     public void setDefaultEnabledTextColor(Color color)
  469.     {
  470.         enabledColor = color;
  471.         invalidate();
  472.     }
  473.  
  474.     /**
  475.      * Returns the current default enabled text color.
  476.      * @see #setDefaultEnabledTextColor
  477.      */
  478.     public Color getDefaultEnabledTextColor()
  479.     {
  480.         return enabledColor;
  481.     }
  482.  
  483.     /**
  484.      * Set the default color for disabled text items.
  485.      * @param color the new default disabled text color
  486.      * @see #getDisabledTextColor
  487.      */
  488.     public void setDisabledTextColor(Color color)
  489.     {
  490.         disabledColor = color;
  491.         invalidate();
  492.     }
  493.  
  494.     /**
  495.      * Returns the current default disabled text color.
  496.      * @return Color - current default disabled text color
  497.      * @see #setDisabledTextColor
  498.      */
  499.     public Color getDisabledTextColor()
  500.     {
  501.         return disabledColor;
  502.     }
  503.  
  504.     /**
  505.      * Set the text color for an item at the given index.
  506.      * @param index the zero-relative index of the item
  507.      * @param color the color, null to use default color
  508.      */
  509.     public void setEnabledTextColor(int index, Color color)
  510.     {
  511.         if (validIndex(index))
  512.         {
  513.             ListItem tempItem = ((ListItem)items.elementAt(index));
  514.             tempItem.color = color;
  515.         }
  516.     }
  517.  
  518.  
  519.     //--------------------------------------------------
  520.     // event methods
  521.     //--------------------------------------------------
  522.  
  523.     /**
  524.      * Processes events for this component.
  525.      * This is a standard Java AWT method which gets called by the AWT
  526.      * to handle this component's events. The default handler for 
  527.      * components dispatches to one of the following methods as needed:
  528.      * action(), gotFocus(), lostFocus(), keyDown(), keyUp(), mouseEnter(),
  529.      * mouseExit(), mouseMove(), mouseDrag(), mouseDown(), or mouseUp().
  530.      *
  531.      * @param evt the event to handle
  532.      * @return true if the event was handled and no further action is needed,
  533.      * false to pass the event to this component's parent
  534.      * @see java.awt.Component#action
  535.      * @see java.awt.Component#gotFocus
  536.      * @see java.awt.Component#lostFocus
  537.      * @see java.awt.Component#keyDown
  538.      * @see java.awt.Component#keyUp
  539.      * @see java.awt.Component#mouseEnter
  540.      * @see java.awt.Component#mouseExit
  541.      * @see java.awt.Component#mouseMove
  542.      * @see java.awt.Component#mouseDrag
  543.      * @see java.awt.Component#mouseDown
  544.      * @see java.awt.Component#mouseUp
  545.      */
  546.     public boolean handleEvent(Event evt)
  547.     {
  548.         long selectTime;
  549.         boolean bDoubleClick;
  550.         int  index = -1;
  551.         String sIndex = "";
  552.  
  553.         switch( evt.id )
  554.         {
  555.             case Event.MOUSE_DOWN:
  556.                 fastDownCount++;
  557.                 bMouseDrawHandled = false;
  558.                 lastDownModifiers = evt.modifiers;
  559.                 if ( (evt.x > -1) && (evt.x < lWidth) )
  560.                 {
  561.                     index = mouseCalcIndex(evt.y);
  562.                     if (index == -1)
  563.                         return true;
  564.  
  565.                     if (bMultipleSelections)
  566.                     {
  567.                         switch (lastDownModifiers)
  568.                         {
  569.                             case 1: // shift
  570.                                 bMouseDrawHandled = true;
  571.                                 shiftSelect(index, false);
  572.                                 break;
  573.  
  574.                             case 2: // ctrl
  575.                                 bMouseDrawHandled = true;
  576.                                 ctrlSelect(index);
  577.                                 break;
  578.  
  579.                             case 3: // ctrl & shift
  580.                                 bMouseDrawHandled = true;
  581.                                 shiftSelect(index, true);
  582.                                 break;
  583.  
  584.                             default:
  585.                                 select(index);
  586.                                 break;
  587.                         }
  588.                         repaint();
  589.                     }
  590.                     else
  591.                     {
  592.                         lastTempIndex = index;
  593.                         if (lastSelected == index)
  594.                             return true;
  595.                         select(index);
  596.                         repaint();
  597.                     }
  598.                 }
  599.                 return true;
  600.  
  601.             case Event.MOUSE_MOVE:
  602.                 if (bMultipleSelections)
  603.                     break;
  604.                 // otherwise continue as MOUSE_DRAG
  605.             case Event.MOUSE_DRAG:
  606.                 if ( (evt.x > -1) && (evt.x < lWidth) )
  607.                 {
  608.                     if (bComboMode)
  609.                     {
  610.                         index = mouseCalcIndex(evt.y);
  611.                         if (index == -1 || index == lastIndex)
  612.                             return true;
  613.                         lastIndex = index;
  614.  
  615.                         select(index);
  616.                         repaint();
  617.                     }
  618.                     else if (evt.id == Event.MOUSE_DRAG)
  619.                     {
  620.                         index = mouseCalcIndex(evt.y);
  621.                         if (index != -1 && index != lastIndex)
  622.                         {
  623.                             if (bMultipleSelections)
  624.                             {
  625.                                 if (lastDownModifiers != 0)
  626.                                     break;
  627.                                 bInternalBlockPaint = true;
  628.                                 makeVisible(index);
  629.                                 bInternalBlockPaint = false;
  630.                                 shiftSelect(index, false);
  631.                             }
  632.                             else
  633.                                 select(index);
  634.                             lastIndex = index;
  635.                         }
  636.                     }
  637.                 }
  638.                 break;
  639.  
  640.             case Event.MOUSE_EXIT:
  641.                 if (!bMultipleSelections && bComboMode)
  642.                     lastIndex = -1;
  643.                 break;
  644.  
  645.             case Event.KEY_ACTION:
  646.                 if (evt.modifiers > 1)
  647.                     break;
  648.  
  649.                 switch(evt.key)
  650.                 {
  651.                     case Event.HOME:  index = keyCalcIndex(0, true); break;
  652.                     case Event.END:   index = keyCalcIndex(items.size() - 1, true); break;
  653.                     case Event.PGUP:  index = keyCalcIndex(-visibleRows, false); break;
  654.                     case Event.PGDN:  index = keyCalcIndex(visibleRows, false); break;
  655.                     case Event.UP:    index = keyCalcIndex(-1, false); break;
  656.                     case Event.DOWN:  index = keyCalcIndex(1, false); break;
  657.                 }
  658.                 if (index == -1)
  659.                     break;
  660.  
  661.                 if (bMultipleSelections)
  662.                 {
  663.                     switch (evt.modifiers)
  664.                     {
  665.                         case 0: // none, regular select
  666.                             break;
  667.  
  668.                         case 1: // shift
  669.                             makeVisible(index);
  670.                             shiftSelect(index, false);
  671.                             return true;
  672.  
  673.                         default:
  674.                             return true;
  675.                     }
  676.                 }
  677.  
  678.                 // regular select, multiple or single
  679.                 select(index);
  680.                 repaint();
  681.                 evt.x = -1;
  682.                 notifyParent(evt, index, false);
  683.                 prevSelectTime = -1;
  684.                 prevSelectRow = -1;
  685.                 return true;
  686.  
  687.             case Event.MOUSE_UP:
  688.                 fastDownCount--;
  689.                 if (bMouseDrawHandled) // multi-selected ctrl or shift
  690.                 {
  691.                     evt.x = -1;
  692.                     notifyParent(evt, -1, false);
  693.                     return true;
  694.                 }
  695.  
  696.                 if (!bMultipleSelections)
  697.                 {
  698.                     index = mouseCalcIndex(evt.y);
  699.                     if ( (index == -1) || (evt.x < 0) || (evt.x >= lWidth) )
  700.                     {
  701.                         fastDownCount = 0;
  702.                         index = lastTempIndex;
  703.                         if (index == -1)
  704.                             return true;
  705.                     }
  706.                 }
  707.  
  708.                 if (bComboMode)
  709.                 {
  710.                     fastDownCount = 0;
  711.                     bDoubleClick = false;
  712.                 }
  713.                 else
  714.                 {
  715.                     // sometimes you get two MOUSE_DOWNS before the first MOUSE_UP
  716.                     if (fastDownCount > 0)
  717.                     {
  718.                         fastDownCount = 0;
  719.                         bDoubleClick = true;
  720.                         prevSelectTime = -1;
  721.                         prevSelectRow = -1;
  722.                     }
  723.                     else
  724.                     {
  725.                         selectTime = System.currentTimeMillis();
  726.                         if ( (prevSelectTime != -1) &&              // valid prevSelectTime
  727.                              (prevSelectRow == index) &&            //
  728.                              ((prevSelectTime + 250) > selectTime)  // A double click
  729.                           )
  730.                         {
  731.                             bDoubleClick = true;
  732.                             prevSelectTime = -1;
  733.                             prevSelectRow = -1;
  734.                         }
  735.                         else
  736.                         {
  737.                             bDoubleClick = false;
  738.                             prevSelectTime = selectTime;
  739.                             prevSelectRow = index;
  740.                         }
  741.                     }
  742.                 }
  743.                 if (lastSelected != index)
  744.                 {
  745.                     select(index);
  746.                     repaint();
  747.                 }
  748.                 if (bMultipleSelections)
  749.                 {
  750.                     notifyParent(evt, lastSelected, bDoubleClick);
  751.                     lastIndex = lastSelected;
  752.                 }
  753.                 else
  754.                 {
  755.                     notifyParent(evt, index, bDoubleClick);
  756.                     lastIndex = index;
  757.                 }
  758.                 lastTempIndex = -1;
  759.                 lastDownModifiers = -1;
  760.                 return true;
  761.  
  762.             case Event.SCROLL_PAGE_DOWN: if (evt.target == VBar) scrollVertical(evt.id, false); else scrollHorizontal(evt.id, false); break;
  763.             case Event.SCROLL_PAGE_UP:   if (evt.target == VBar) scrollVertical(evt.id, false); else scrollHorizontal(evt.id, false); break;
  764.             case Event.SCROLL_LINE_DOWN: if (evt.target == VBar) scrollVertical(evt.id, false); else scrollHorizontal(evt.id, false); break;
  765.             case Event.SCROLL_LINE_UP:   if (evt.target == VBar) scrollVertical(evt.id, false); else scrollHorizontal(evt.id, false); break;
  766.             case Event.SCROLL_ABSOLUTE:  if (evt.target == VBar) scrollVertical(((Integer)evt.arg).intValue(), true); else scrollHorizontal(((Integer)evt.arg).intValue(), true); break;
  767.         }
  768.         return false;
  769.     }
  770.  
  771.  
  772.     //--------------------------------------------------
  773.     // class methods
  774.     //--------------------------------------------------
  775.  
  776.  
  777.     //--------------------------------------------------
  778.     // member methods
  779.     //--------------------------------------------------
  780.  
  781.     /**
  782.      * Sets the mode of the ImageListBox to "MultiColumnListBox
  783.      * Mode".  This method always sets the border type to BORDER_NONE
  784.      * and conditionally sets whether the grid should be displayed.
  785.      * @param bCellBorders true to display the cell grid,
  786.      * false to not display the grid
  787.      * @see #BORDER_NONE
  788.      */
  789.     public synchronized void setMultiColumnMode(boolean bCellBorders)
  790.     {
  791.         bComboMode = false;
  792.         yAdj = 2;
  793.         setBorderType(BORDER_NONE);
  794.         setCellBorders(bCellBorders);
  795.     }
  796.  
  797.     /**
  798.      * Adds an item to the end of the list and enables the item.
  799.      * @param item the item to be added
  800.      * @see #setListItems(java.lang.String[])
  801.      * @see #addItem(java.lang.String, boolean)
  802.      * @see #addItem(java.awt.Image, java.lang.String)
  803.      * @see #addItem(java.awt.Image, java.lang.String, boolean)
  804.      * @see #addItem(java.awt.Image, java.lang.String, boolean, java.awt.Color)
  805.      */
  806.     public synchronized void addItem(String item)
  807.     {
  808.         addItem(new ListItem((Image)null, item, true, fm, bCellBorders));
  809.     }
  810.  
  811.     /**
  812.      * Adds the string array to the list.
  813.      * @param items items to add to the list
  814.      * @see #getListItems
  815.      * @see #setListItems(java.lang.String[])
  816.      * @see #addItem(java.lang.String)
  817.      * @see #addItem(java.lang.String, boolean)
  818.      * @see #addItem(java.awt.Image, java.lang.String)
  819.      * @see #addItem(java.awt.Image, java.lang.String, boolean)
  820.      * @see #addItem(java.awt.Image, java.lang.String, boolean, java.awt.Color)
  821.      */
  822.     public void setListItems(String[] items)
  823.     {
  824.         clear();
  825.         for (int i = 0; i < items.length; ++i)
  826.         {
  827.             addItem(items[i]);
  828.         }
  829.     }
  830.  
  831.     /**
  832.      * Returns the current list as a array.
  833.      * @return String[] current list
  834.      * @see #setListItems
  835.      */
  836.     public String[] getListItems()
  837.     {
  838.         int len = countItems();
  839.         String[] items = new String[len];
  840.         for (int i = 0; i < len; ++i)
  841.         {
  842.             items[i] = getItem(i);
  843.         }
  844.         return items;
  845.     }
  846.  
  847.     /**
  848.      * Adds an item to the end of the list and conditionally enables
  849.      * it.
  850.      * @param item the item to be added
  851.      * @param bEnabled if true, enable the item; if false, disable
  852.      * the item
  853.      * @see #setListItems(java.lang.String[])
  854.      * @see #addItem(java.lang.String)
  855.      * @see #addItem(java.awt.Image, java.lang.String)
  856.      * @see #addItem(java.awt.Image, java.lang.String, boolean)
  857.      * @see #addItem(java.awt.Image, java.lang.String, boolean, java.awt.Color)
  858.      */
  859.     public synchronized void addItem(String item, boolean bEnabled)
  860.     {
  861.         addItem(new ListItem((Image)null, item, bEnabled, fm, bCellBorders));
  862.     }
  863.  
  864.     /**
  865.      * Adds an item with an image to the end of the list and enables
  866.      * it.
  867.      * @param image the image to display on the item line
  868.      * @param item the item to be added
  869.      * @see #setListItems(java.lang.String[])
  870.      * @see #addItem(java.lang.String)
  871.      * @see #addItem(java.lang.String, boolean)
  872.      * @see #addItem(java.awt.Image, java.lang.String, boolean)
  873.      * @see #addItem(java.awt.Image, java.lang.String, boolean, java.awt.Color)
  874.      */
  875.     public synchronized void addItem(Image image, String item)
  876.     {
  877.         addItem(new ListItem(image, item, true, fm, bCellBorders));
  878.     }
  879.  
  880.     /**
  881.      * Adds an item with an image to the end of the list and
  882.      * conditionally enables it.
  883.      * @param image the image to display on item line
  884.      * @param item the item to be added
  885.      * @param bEnabled if true, enable the item; if false, disable the item
  886.      * @see #setListItems(java.lang.String[])
  887.      * @see #addItem(java.lang.String)
  888.      * @see #addItem(java.lang.String, boolean)
  889.      * @see #addItem(java.awt.Image, java.lang.String)
  890.      * @see #addItem(java.awt.Image, java.lang.String, boolean, java.awt.Color)
  891.      */
  892.     public synchronized void addItem(Image image, String item, boolean bEnabled)
  893.     {
  894.         addItem(new ListItem(image, item, bEnabled, fm, bCellBorders));
  895.     }
  896.  
  897.     /**
  898.      * Adds an item with an image to the end of the list and
  899.      * conditionally enables it.
  900.      * @param image the image to display on item line
  901.      * @param item the item to be added
  902.      * @param bEnabled if true, enable the item; if false, disable the item
  903.      * @param color text color of item
  904.      * @see #setListItems(java.lang.String[])
  905.      * @see #addItem(java.lang.String)
  906.      * @see #addItem(java.lang.String, boolean)
  907.      * @see #addItem(java.awt.Image, java.lang.String)
  908.      * @see #addItem(java.awt.Image, java.lang.String, boolean)
  909.      */
  910.     public synchronized void addItem(Image image, String item, boolean bEnabled, Color color)
  911.     {
  912.         ListItem li = new ListItem(image, item, bEnabled, fm, bCellBorders);
  913.         li.color = color;
  914.         addItem(li);
  915.     }
  916.  
  917.     private void addItem(ListItem li)
  918.     {
  919.         items.addElement(li);
  920.         updateWidth(li);
  921.         if (!bInternalBlockPaint) repaint();
  922.     }
  923.  
  924.     /**
  925.      * Inserts an item with an image at a specific zero-relative index and
  926.      * conditionally enables it.
  927.      * @param index the zero-relative index to insert at
  928.      * @param image the image to display on the item line
  929.      * @param item the item to be added
  930.      * @param bEnabled if true, enable the item; if false, disable the item
  931.      */
  932.     public synchronized void insertItem(int index, Image image, String item, boolean bEnabled)
  933.     {
  934.         ListItem li = null;
  935.         if ( validIndex(index) )
  936.         {
  937.             items.insertElementAt(li = new ListItem(image, item, bEnabled, fm, bCellBorders), index);
  938.             bAllDirty = true;
  939.             if (lastSelected >= index)
  940.                 lastSelected++;
  941.         }
  942.         else
  943.             items.addElement(li = new ListItem(image, item, bEnabled, fm, bCellBorders));
  944.         updateWidth(li);
  945.  
  946.         if (!bInternalBlockPaint) repaint();
  947.     }
  948.  
  949.     /**
  950.      * Inserts a vector list of items at a specific zero-relative index and
  951.      * conditionally enables them.
  952.      * @param index the zero-relative index to insert at
  953.      * @param itemVector the item vector to be added
  954.      * @param image the image to display for all inserted items
  955.      * @param bEnabled if true, enable the items; if false, disable the items
  956.      */
  957.     public synchronized void insertItems(int index, Vector itemVector, Image image, boolean bEnabled)
  958.     {
  959.         int s = itemVector.size();
  960.         int x = 0;
  961.         int idx = index;
  962.         if ( validIndex(index) )
  963.         {
  964.             for (x = 0; x < s; x++)
  965.                 items.insertElementAt(new ListItem(image, (String) itemVector.elementAt(x), bEnabled, fm, bCellBorders), index++);
  966.         }
  967.         else
  968.         {
  969.             for (x = 0; x < s; x++)
  970.                 items.addElement(new ListItem(image, (String) itemVector.elementAt(x), bEnabled, fm, bCellBorders));
  971.         }
  972.         deselectAll();
  973.         bAllDirty = true;
  974.         updateWidths(fm);
  975.  
  976.         if (!bInternalBlockPaint) repaint();
  977.     }
  978.  
  979.     /**
  980.      * Returns the number of items in the list.
  981.      * @return number of items in the list
  982.      * @see #getItem
  983.      */
  984.     public int countItems()
  985.     {
  986.         return items.size();
  987.     }
  988.  
  989.     /**
  990.      * Gets the item associated with the specified zero-relative index.
  991.      * @param index the zero-relative position of the item
  992.      * @return item text, or null if index is invalid
  993.      * @see #countItems
  994.      */
  995.     public String getItem(int index)
  996.     {
  997.         if (validIndex(index))
  998.             return ((ListItem)items.elementAt(index)).sText;
  999.         else
  1000.             return null;
  1001.     }
  1002.  
  1003.     /**
  1004.      * Gets the image associated with the specified zero-relative index.
  1005.      * @param index the zero-relative position of the item
  1006.      * @return image at index, or null if index is
  1007.      * invalid
  1008.      * @see #countItems
  1009.      */
  1010.     public Image getImage(int index)
  1011.     {
  1012.         if (validIndex(index))
  1013.             return ((ListItem)items.elementAt(index)).image;
  1014.         else
  1015.             return null;
  1016.     }
  1017.  
  1018.     /**
  1019.      * Change the image associated with an item at a
  1020.      * specific zero-relative index.
  1021.      * @param index the zero-relative position of the item
  1022.      * @param image the image to associate with an item
  1023.      */
  1024.     public void changeImage(int index, Image image)
  1025.     {
  1026.         if (validIndex(index))
  1027.         {
  1028.             ListItem tempItem = ((ListItem)items.elementAt(index));
  1029.             tempItem.image = image;
  1030.             tempItem.bDirty = true;
  1031.             if (!bInternalBlockPaint) repaint();
  1032.         }
  1033.     }
  1034.  
  1035.     /**
  1036.      * Change the text associated with an item at a
  1037.      * specific zero-relative index.
  1038.      * @param index the zero-relative position of the item
  1039.      * @param text the text to associate with an item
  1040.      */
  1041.     public void changeText(int index, String text)
  1042.     {
  1043.         if (validIndex(index))
  1044.         {
  1045.             ListItem tempItem = ((ListItem)items.elementAt(index));
  1046.             tempItem.sText = text;
  1047.             tempItem.bDirty = true;
  1048.             tempItem.updateWidth(fm);
  1049.             updateWidth(tempItem);
  1050.             if (!bInternalBlockPaint) repaint();
  1051.         }
  1052.     }
  1053.  
  1054.     /**
  1055.      * Set a flag indicating that the item at the given zero-relative index
  1056.      * has been edited.
  1057.      * @param index the zero-relative position of the item
  1058.      * @param bCond "edited" flag
  1059.      * @see #getEdited
  1060.      */
  1061.     public void setEdited(int index, boolean bCond)
  1062.     {
  1063.         if (validIndex(index))
  1064.         {
  1065.             ListItem tempItem = ((ListItem)items.elementAt(index));
  1066.             tempItem.bEdited = bCond;
  1067.         }
  1068.     }
  1069.  
  1070.     /**
  1071.      * Get the "edited" flag state for an item at the given
  1072.      * zero-relative index.
  1073.      * @param index the zero-relative position of the item
  1074.      * @return true if flagged as edited, false if not
  1075.      * @see #setEdited
  1076.      */
  1077.     public boolean getEdited(int index)
  1078.     {
  1079.         if (validIndex(index))
  1080.         {
  1081.             ListItem tempItem = ((ListItem)items.elementAt(index));
  1082.             return tempItem.bEdited;
  1083.         }
  1084.  
  1085.         return false;
  1086.     }
  1087.  
  1088.     /**
  1089.      * Enables an item in the list.
  1090.      * @param index the zero-relative position of the item
  1091.      * @see #disable
  1092.      */
  1093.     public void enable(int index)
  1094.     {
  1095.         if (validIndex(index))
  1096.         {
  1097.             ListItem tempItem = ((ListItem)items.elementAt(index));
  1098.             if (!tempItem.bEnabled)
  1099.             {
  1100.                 tempItem.bEnabled = true;
  1101.                 tempItem.bDirty = true;
  1102.                 if (!bInternalBlockPaint) repaint();
  1103.             }
  1104.         }
  1105.     }
  1106.  
  1107.     /**
  1108.      * Disables an item in the list.
  1109.      * @param index the zero-relative position of the item
  1110.      * @see #enable
  1111.      */
  1112.     public void disable(int index)
  1113.     {
  1114.         if (validIndex(index))
  1115.         {
  1116.             ListItem tempItem = ((ListItem)items.elementAt(index));
  1117.             if (tempItem.bEnabled)
  1118.             {
  1119.                 tempItem.bEnabled = false;
  1120.                 tempItem.bDirty = true;
  1121.                 deselect(index);
  1122.                 if (!bInternalBlockPaint) repaint();
  1123.             }
  1124.         }
  1125.     }
  1126.  
  1127.     /**
  1128.      * Enable or disable a specific item in the list.
  1129.      * @param index the zero-relative position of the item
  1130.      * @param cond if true, enable the item; if false, disable the
  1131.      * item
  1132.      * @see #isEnabled
  1133.      */
  1134.     public void enable(int index, boolean cond)
  1135.     {
  1136.         if (cond)
  1137.             enable(index);
  1138.         else
  1139.             disable(index);
  1140.     }
  1141.  
  1142.     /**
  1143.      * Get the enabled state of a specific item in the list.
  1144.      * @param index the zero-relative position of the item in the list
  1145.      * @return true if the item is enabled, false
  1146.      * if the item is disabled.
  1147.      * @see #enable
  1148.      */
  1149.     public boolean isEnabled(int index)
  1150.     {
  1151.         if (validIndex(index))
  1152.         {
  1153.             ListItem tempItem = ((ListItem)items.elementAt(index));
  1154.             return tempItem.bEnabled;
  1155.         }
  1156.  
  1157.         return false;
  1158.     }
  1159.  
  1160.    /**
  1161.      * Clears the list.
  1162.      * @see #delItem
  1163.      * @see #delItems
  1164.      */
  1165.     public synchronized void clear()
  1166.     {
  1167.         items = new Vector();
  1168.  
  1169.         nTopRow = 0;
  1170.         visibleIndex = -1;
  1171.         lastDownModifiers = -1;
  1172.         lastSelected = -1;
  1173.         lastIndex = -1;
  1174.         lastTempIndex = -1;
  1175.         countSelected = 0;
  1176.         prevSelectTime = -1;
  1177.         prevSelectRow = -1;
  1178.         VBar.setValues(1, 1, 0, 2);
  1179.         VBar.hide();
  1180.         bVBarVisible = false;
  1181.         HBar.setValues(1, 1, 0, 2);
  1182.         HBar.hide();
  1183.         bHBarVisible = false;
  1184.         bAllDirty = true;
  1185.         bInternalBlockPaint = false;
  1186.         bBlockPaint = false;
  1187.         longestLineValue = 0;
  1188.         xCoord = 0;
  1189.         repaint();
  1190.     }
  1191.  
  1192.     /**
  1193.      * Delete an item from the list.
  1194.      * @param index the zero-relative index of the item to delete
  1195.      * @see #delItems
  1196.      * @see #delSelectedItems
  1197.      */
  1198.     public synchronized void delItem(int index)
  1199.     {
  1200.         if (validIndex(index))
  1201.         {
  1202.             deselect(index);
  1203.             items.removeElementAt(index);
  1204.             bAllDirty = true;
  1205.             scrollVertical(nTopRow, true);
  1206.             updateWidths(null);
  1207.             if (!bInternalBlockPaint) repaint();
  1208.         }
  1209.     }
  1210.  
  1211.     /**
  1212.      * Delete multiple items from the list.
  1213.      * Note that the end index must be greater than or
  1214.      * equal to the start index.
  1215.      * @param start the zero-relative start index of the items
  1216.      * @param end the zero-relative end index of the items
  1217.      * @see #delItem
  1218.      * @see #delSelectedItems
  1219.      */
  1220.     public synchronized void delItems(int start, int end)
  1221.     {
  1222.         int s = items.size();
  1223.         if (s > 0)
  1224.         {
  1225.             if (end >= s)
  1226.                 end = s - 1;
  1227.             if (start < 0)
  1228.                 start = 0;
  1229.             if (start <= end)
  1230.             {
  1231.                 bInternalBlockPaint = true;
  1232.                 for (int i = end; i >= start; i--)
  1233.                 {
  1234.                     deselect(i);
  1235.                     items.removeElementAt(i);
  1236.                 }
  1237.                 bInternalBlockPaint = false;
  1238.                 bAllDirty = true;
  1239.                 scrollVertical(nTopRow, true);
  1240.                 updateWidths(null);
  1241.                 repaint();
  1242.             }
  1243.         }
  1244.     }
  1245.  
  1246.     /**
  1247.      * Delete the selected items from the list.
  1248.      * @see #delItem
  1249.      * @see #delItems
  1250.      */
  1251.     public synchronized void delSelectedItems()
  1252.     {
  1253.         int s = items.size();
  1254.  
  1255.         bInternalBlockPaint = true;
  1256.         for (int x = 0; x < s; )
  1257.         {
  1258.             ListItem tempItem = (ListItem) items.elementAt(x);
  1259.             if (tempItem.bSelected)
  1260.             {
  1261.                 deselect(x);
  1262.                 items.removeElementAt(x);
  1263.                 s--;
  1264.             }
  1265.             else
  1266.                 x++;
  1267.         }
  1268.         bAllDirty = true;
  1269.         scrollVertical(nTopRow, true);
  1270.         updateWidths(null);
  1271.         bInternalBlockPaint = false;
  1272.         repaint();
  1273.     }
  1274.  
  1275.     /**
  1276.      * Get the zero-relative index of the selected item in the list
  1277.      * @return the zero-relative index of selected item, or -1 if no item is
  1278.      * selected
  1279.      * @see #select
  1280.      * @see #deselect
  1281.      * @see #isSelected
  1282.      */
  1283.     public synchronized int getSelectedIndex()
  1284.     {
  1285.         return lastSelected;
  1286.     }
  1287.  
  1288.     /**
  1289.      * Returns the selected indexes in the list.
  1290.      * @return int[] - array of selected zero-relative indexes
  1291.      * @see #select
  1292.      * @see #deselect
  1293.      * @see #isSelected
  1294.      */
  1295.     public synchronized int[] getSelectedIndexes()
  1296.     {
  1297.         int sel[] = new int[countSelected];
  1298.  
  1299.         if (countSelected == 1)
  1300.             sel[0] = lastSelected;
  1301.         else if (countSelected > 1)
  1302.         {
  1303.             int x = 0;
  1304.             int s = items.size();
  1305.             for (int i = 0; i < s; i++)
  1306.             {
  1307.                 ListItem tempItem = (ListItem)items.elementAt(i);
  1308.                 if (tempItem.bSelected)
  1309.                 {
  1310.                     sel[x++] = i;
  1311.                     if (x == countSelected)
  1312.                         break;
  1313.                 }
  1314.             }
  1315.         }
  1316.  
  1317.         return sel;
  1318.     }
  1319.  
  1320.     /**
  1321.      * Returns the currently selected item in the list.
  1322.      * @return the currently selected item, or null if
  1323.      * no item is selected.
  1324.      * @see #getSelectedItems
  1325.      * @see #select
  1326.      * @see #deselect
  1327.      * @see #isSelected
  1328.      */
  1329.     public synchronized String getSelectedItem()
  1330.     {
  1331.         return (lastSelected < 0) ? null : getItem(lastSelected);
  1332.     }
  1333.  
  1334.     /**
  1335.      * Returns the selected items in the list.
  1336.      * @return an array of selected items in the list
  1337.      * @see #getSelectedItem
  1338.      * @see #select
  1339.      * @see #deselect
  1340.      * @see #isSelected
  1341.      */
  1342.     public synchronized String[] getSelectedItems()
  1343.     {
  1344.         String str[] = new String[countSelected];
  1345.         ListItem tempItem;
  1346.  
  1347.         if (!bMultipleSelections)
  1348.         {
  1349.             if (lastSelected != -1)
  1350.             {
  1351.                 tempItem = (ListItem)items.elementAt(lastSelected);
  1352.                 str[0] = tempItem.sText;
  1353.             }
  1354.         }
  1355.         else if (countSelected > 0)
  1356.         {
  1357.             int x = 0;
  1358.             int s = items.size();
  1359.             for (int i = 0; i < s; i++)
  1360.             {
  1361.                 tempItem = (ListItem)items.elementAt(i);
  1362.                 if (tempItem.bSelected)
  1363.                 {
  1364.                     str[x] = tempItem.sText;
  1365.                     if (++x == countSelected)
  1366.                         break;
  1367.                 }
  1368.             }
  1369.         }
  1370.  
  1371.         return str;
  1372.     }
  1373.  
  1374.     /**
  1375.      * Returns the current list box label.
  1376.      * @return the current list box label
  1377.      */
  1378.     public synchronized String getLabel()
  1379.     {
  1380.         return new String(ilbLabel);
  1381.     }
  1382.  
  1383.     /**
  1384.      * Select the item at the specified index.
  1385.      * This method deselects all others when multiple
  1386.      * selections not enabled.
  1387.      * @param index the zero-relative position of the item to select
  1388.      * @see #getSelectedItem
  1389.      * @see #deselect
  1390.      * @see #isSelected
  1391.      */
  1392.     public synchronized void select(int index)
  1393.     {
  1394.         if ( isEnabled(index) )
  1395.         {
  1396.             ListItem listItem = null;
  1397.             if (bMultipleSelections)
  1398.             {
  1399.                 int s = items.size();
  1400.                 for (int i = 0; i < s; i++)
  1401.                 {
  1402.                     listItem = (ListItem)items.elementAt(i);
  1403.                     if (i == index)
  1404.                     {
  1405.                         if (!listItem.bSelected)
  1406.                         {
  1407.                             listItem.bSelected = true;
  1408.                             listItem.bDirty = true;
  1409.                         }
  1410.                     }
  1411.                     else
  1412.                     {
  1413.                         if (listItem.bSelected)
  1414.                         {
  1415.                             listItem.bSelected = false;
  1416.                             listItem.bDirty = true;
  1417.                         }
  1418.                     }
  1419.                 }
  1420.             }
  1421.             else
  1422.             {
  1423.                 if (lastSelected != index)
  1424.                 {
  1425.                     if (lastSelected != -1)
  1426.                         deselect(lastSelected);
  1427.  
  1428.                     listItem = (ListItem)items.elementAt(index);
  1429.                     listItem.bSelected = true;
  1430.                     listItem.bDirty = true;
  1431.                 }
  1432.             }
  1433.             lastSelected = index;
  1434.             countSelected = 1;
  1435.             makeVisible(index);
  1436.         }
  1437.     }
  1438.  
  1439.     /**
  1440.      * Selects the first item in the list which has exactly
  1441.      * matching text.
  1442.      * @param str the String to select in the list
  1443.      */
  1444.     public synchronized void select(String str)
  1445.     {
  1446.         ListItem li;
  1447.         int z = items.size();
  1448.         for (int i = 0; i < z; i++)
  1449.         {
  1450.             li = (ListItem) items.elementAt(i);
  1451.             if (li.sText.equals(str))
  1452.             {
  1453.                 if (li.bEnabled)
  1454.                     select(i);
  1455.                 return;
  1456.             }
  1457.         }
  1458.     }
  1459.  
  1460.     /**
  1461.      * Select an index in a multiple-selection-enabled ImageListBox
  1462.      * using Shift, Ctrl or Ctrl-Shift modifiers to mimic mouse
  1463.      * selecting with the Shift, Ctrl or Ctrl-Shift modifiers.
  1464.      * @param index the zero-relative position of the item to select multiple
  1465.      * @param bShift boolean indicating whether to select with
  1466.      * Shift modifier
  1467.      * @param bControl boolean indicating whether to select with
  1468.      * Ctrl modifier
  1469.      */
  1470.     public synchronized void selectMultiple(int index, boolean bShift, boolean bControl)
  1471.     {
  1472.         if (!bMultipleSelections)
  1473.         {
  1474.             bShift = false;
  1475.             bControl = false;
  1476.         }
  1477.         if (bShift)
  1478.             shiftSelect(index, bControl);
  1479.         else if (bControl)
  1480.             ctrlSelect(index);
  1481.         else
  1482.             select(index);
  1483.     }
  1484.  
  1485.     /**
  1486.      * Selects all items in the list.
  1487.      * @see #deselectAll
  1488.      */
  1489.     public synchronized void selectAll()
  1490.     {
  1491.         if (!bMultipleSelections)
  1492.             return;
  1493.  
  1494.         int s = items.size();
  1495.         ListItem li;
  1496.         for (int i = 0; i < s; i++)
  1497.         {
  1498.             li = (ListItem)items.elementAt(i);
  1499.             if (li.bEnabled)
  1500.                 li.bSelected = true;
  1501.         }
  1502.         countSelected = s;
  1503.         lastSelected = s - 1;
  1504.         repaint();
  1505.     }
  1506.  
  1507.     /**
  1508.      * Deselects the item at the specified index.
  1509.      * @param index the zero-relative position of the item to deselect
  1510.      * @see #select
  1511.      * @see #getSelectedItem
  1512.      * @see #isSelected
  1513.      */
  1514.     public synchronized void deselect(int index)
  1515.     {
  1516.         if (validIndex(index))
  1517.         {
  1518.             ListItem listItem = (ListItem)items.elementAt(index);
  1519.             if (listItem.bSelected)
  1520.             {
  1521.                 if (lastSelected == index)
  1522.                     lastSelected = -1;
  1523.                 listItem.bSelected = false;
  1524.                 listItem.bDirty = true;
  1525.                 countSelected--;
  1526.                 if (!bInternalBlockPaint) repaint();
  1527.             }
  1528.         }
  1529.     }
  1530.  
  1531.     /**
  1532.      * Deselects all items in the list.
  1533.      * @see #selectAll
  1534.      */
  1535.     public synchronized void deselectAll()
  1536.     {
  1537.         ListItem li;
  1538.         if (!bMultipleSelections)
  1539.         {
  1540.             if (lastSelected != -1)
  1541.             {
  1542.                 li = (ListItem)items.elementAt(lastSelected);
  1543.                 li.bSelected = false;
  1544.                 li.bDirty = true;
  1545.             }
  1546.         }
  1547.         else
  1548.         {
  1549.             int s = items.size();
  1550.             for (int i = 0; i < s; i++)
  1551.             {
  1552.                 li = (ListItem)items.elementAt(i);
  1553.                 if (li.bSelected)
  1554.                 {
  1555.                     li.bSelected = false;
  1556.                     li.bDirty = true;
  1557.                 }
  1558.             }
  1559.         }
  1560.         lastSelected = -1;
  1561.         countSelected = 0;
  1562.         repaint();
  1563.     }
  1564.  
  1565.     /**
  1566.      * Get the selected state of the item at the given index.
  1567.      * @param index the zero-relative index of the item to be checked
  1568.      * @return true if the item at the specified index
  1569.      * is selected; false if it is not selected
  1570.      * @see #select
  1571.      * @see #deselect
  1572.      * @see #isSelected
  1573.      */
  1574.     public synchronized boolean isSelected(int index)
  1575.     {
  1576.         if (validIndex(index))
  1577.         {
  1578.             ListItem listItem = (ListItem)items.elementAt(index);
  1579.             return listItem.bSelected;
  1580.         }
  1581.         return false;
  1582.     }
  1583.  
  1584.     /**
  1585.      * Returns the number of visible lines in this list.
  1586.      * @return the number of visible lines in the list.
  1587.      */
  1588.     public int getRows()
  1589.     {
  1590.         return visibleRows;
  1591.     }
  1592.  
  1593.     /**
  1594.      * Returns true if this list allows multiple selections.
  1595.      * @return true if multiple selections allowed, false otherwise
  1596.      * @see #setMultipleSelections
  1597.      */
  1598.     public boolean allowsMultipleSelections()
  1599.     {
  1600.         return bMultipleSelections;
  1601.     }
  1602.  
  1603.     /**
  1604.      * Sets whether this list should allow multiple selections
  1605.      * or not.
  1606.      * @param cond whether to allow multiple selections
  1607.      * @see #allowsMultipleSelections
  1608.      */
  1609.     public void setMultipleSelections(boolean cond)
  1610.     {
  1611.         if (cond != bMultipleSelections)
  1612.         {
  1613.             if (!cond)  // deselect first because deselect works differently according to bMultipleSelections flag
  1614.                 deselectAll();
  1615.             bMultipleSelections = cond;
  1616.         }
  1617.     }
  1618.  
  1619.     /**
  1620.      * Gets the index of the item that was last made visible by
  1621.      * the method makeVisible.
  1622.      * @return the zero-relative index of the item last made visible by the
  1623.      * makeVisible method
  1624.      * @see #makeVisible
  1625.      */
  1626.     public int getVisibleIndex()
  1627.     {
  1628.         return visibleIndex;
  1629.     }
  1630.  
  1631.     /**
  1632.      * Forces the item at the specified index to be visible in
  1633.      * the window.
  1634.      * @param index the zero-relative position of the item
  1635.      * @see #getVisibleIndex
  1636.      */
  1637.     public synchronized void makeVisible(int index)
  1638.     {
  1639.         visibleIndex = index;
  1640.         if ( nTopRow > index )
  1641.             scrollVertical(index, true);
  1642.         else if (index >= (nTopRow + visibleRows))
  1643.             scrollVertical(index - visibleRows + 1, true);
  1644.     }
  1645.  
  1646.     /**
  1647.      * Forces the item at the specified index to be visible at
  1648.      * the top of the window.
  1649.      * @param index the zero-relative position of the item
  1650.      */
  1651.     public void setTopRow(int index)
  1652.     {
  1653.         int s = items.size();
  1654.         if (s < visibleRows)
  1655.             index = 0;
  1656.         else if (index > (s - visibleRows))
  1657.             index = s - visibleRows;
  1658.  
  1659.         if (nTopRow != index)
  1660.         {
  1661.             nTopRow = index;
  1662.             bAllDirty = true;
  1663.             invalidate();
  1664.         }
  1665.     }
  1666.  
  1667.     /**
  1668.      * Returns the preferred dimensions needed for the list with
  1669.      * the specified amount of rows.
  1670.      * @param rows number of rows in the list
  1671.      * @return the preferred of this list with the given the number of rows
  1672.      */
  1673.     /**
  1674.      * Returns the recommended dimensions to properly display this component.
  1675.      * This is a standard Java AWT method which gets called to determine
  1676.      * the recommended size of this component. 
  1677.      *
  1678.      * @see #minimumSize
  1679.      */
  1680.     public Dimension preferredSize(int rows)
  1681.     {
  1682.         Dimension d = minimumSize(rows);
  1683.         Dimension s = size();
  1684.         return new Dimension(Math.max(d.width, s.width), Math.max(d.height, s.height));
  1685.     }
  1686.  
  1687.     /**
  1688.      * Returns the preferred dimensions needed for the list.
  1689.      * @return the preferred size with the specified number of rows if the
  1690.      * row size is greater than 0.
  1691.      */
  1692.     public Dimension preferredSize()
  1693.     {
  1694.         if (rowsToShow > 0)
  1695.             return preferredSize(rowsToShow);
  1696.  
  1697.         return preferredSize(items.size());
  1698.     }
  1699.  
  1700.     /**
  1701.      * Returns the minimum dimensions needed for the amount of rows
  1702.      * in the list.
  1703.      * @param rows minimum amount of rows in the list
  1704.      * @return the minimum size of this list with the given the number of rows
  1705.      */
  1706.     public Dimension minimumSize(int rows)
  1707.     {
  1708.         font = getFont();
  1709.         if (font != null)
  1710.         {
  1711.             fm = getFontMetrics(font);
  1712.             if (fm != null)
  1713.             {
  1714.                 fontHeight = fm.getHeight();
  1715.  
  1716.                 if (bCellBorders)
  1717.                     cellHt = fontHeight+5;
  1718.                 else
  1719.                     cellHt = fontHeight+1;
  1720.  
  1721.                 return new Dimension( ((fm.stringWidth("WN") * colsToShow) / 2) + LINE_SLOP, (rows * cellHt + borderWidth + 4) );
  1722.             }
  1723.         }
  1724.         return new Dimension(borderWidth + LINE_SLOP, borderWidth + 4);
  1725.     }
  1726.  
  1727.     /**
  1728.      * Returns the minimum dimensions to properly display this component.
  1729.      * This is a standard Java AWT method which gets called to determine
  1730.      * the minimum size of this component. 
  1731.      * Considerations include the number of rows in the list.
  1732.      * @see #preferredSize
  1733.      */
  1734.     public Dimension minimumSize()
  1735.     {
  1736.         if (rowsToShow > 0)
  1737.             return minimumSize(rowsToShow);
  1738.         return minimumSize(items.size());
  1739.     }
  1740.  
  1741.     /**
  1742.      * Tells this component that it has been added to a container.
  1743.      * This is a standard Java AWT method which gets called by the AWT when 
  1744.      * this component is added to a container. Typically, it is used to 
  1745.      * create this component's peer.
  1746.      * It is overridden here to handle list metrics after the peer is created.
  1747.      *
  1748.      * @see java.awt.Container#removeNotify
  1749.      */
  1750.     public void addNotify()
  1751.     {
  1752.         super.addNotify();
  1753.         font = getFont();
  1754.         fm = getFontMetrics(font);
  1755.         fontHeight = fm.getHeight();
  1756.         updateWidths(fm);
  1757.     }
  1758.  
  1759.     /**
  1760.      * Sets the number of columns to be used by minimumSize().
  1761.      * @param columns the number of columns
  1762.      */
  1763.     public synchronized void setColumns(int columns)
  1764.     {
  1765.         if (colsToShow != columns)
  1766.         {
  1767.             colsToShow = columns;
  1768.             invalidate();
  1769.         }
  1770.     }
  1771.  
  1772.     /**
  1773.      * Blocks the repainting of the control.
  1774.      * @param cond conditionally block painting
  1775.      */
  1776.     public synchronized void blockPaint(boolean cond)
  1777.     {
  1778.         bBlockPaint = cond;
  1779.         if (!bBlockPaint)
  1780.             repaint();
  1781.     }
  1782.  
  1783.     /**
  1784.      * Sets this component's text font.
  1785.      * This is a standard Java AWT method which gets called to change
  1786.      * the font used for drawing text in this component.
  1787.      * In this case the text is in the list box items.
  1788.      * @param f the new font to use for drawing text
  1789.      * @see java.awt.Component#getFont
  1790.      * @see #getListBoxFont
  1791.      * @see #setListBoxFont
  1792.      */
  1793.     public synchronized void setFont(Font f)
  1794.     {
  1795.         if (f == null)
  1796.             return;
  1797.         super.setFont(f);
  1798.         fm = getFontMetrics(f);
  1799.         updateWidths(fm);
  1800.         xCoord = 0;
  1801.         if (bOsFlag)
  1802.         {
  1803.             bAllDirty = true;
  1804.             invalidate();
  1805.         }
  1806.     }
  1807.  
  1808.     /**
  1809.      * Set the font for the items in the list box. Note: this method is the
  1810.      * same as setFont().
  1811.      * @param f new font to use for list box items
  1812.      * @see #getListBoxFont
  1813.      */
  1814.     public synchronized void setListBoxFont(Font f)
  1815.     {
  1816.         setFont(f);
  1817.     }
  1818.  
  1819.     /**
  1820.      * Get the font used for the list box items.
  1821.      * @see #setListBoxFont
  1822.      */
  1823.     public synchronized Font getListBoxFont()
  1824.     {
  1825.         return super.getFont();
  1826.     }
  1827.  
  1828.     /**
  1829.      * Scroll the ImageListBox vertically.
  1830.      * @param info either an absolute value or Event.SCROLL_PAGE_DOWN,
  1831.      * Event.SCROLL_PAGE_UP, Event.SCROLL_LINE_DOWN, Event.SCROLL_LINE_UP
  1832.      * the range for absolute value should be between 0 and number of rows in ImageListBox
  1833.      * @param bAbsolute whether to treat the info as an absolute value or as one of the constants
  1834.      */
  1835.     public synchronized void scrollVertical(int info, boolean bAbsolute)
  1836.     {
  1837.         int temp = nTopRow;
  1838.  
  1839.         if (visibleRows == 0)
  1840.             temp = 0;
  1841.         else
  1842.         {
  1843.             if (bAbsolute)
  1844.                 temp = info;
  1845.             else
  1846.             {
  1847.                 switch (info)
  1848.                 {
  1849.                     case Event.SCROLL_PAGE_DOWN:    temp += visibleRows; break;
  1850.                     case Event.SCROLL_PAGE_UP:      temp -= visibleRows; break;
  1851.                     case Event.SCROLL_LINE_DOWN:    temp += 1; break;
  1852.                     case Event.SCROLL_LINE_UP:      temp -= 1; break;
  1853.                 }
  1854.             }
  1855.  
  1856.             if (temp < 0)
  1857.                 temp = 0;
  1858.             else if (temp > (items.size() - visibleRows))
  1859.             {
  1860.                 temp = items.size() - visibleRows;
  1861.                 if (temp < 0)
  1862.                     temp = 0;
  1863.             }
  1864.         }
  1865.  
  1866.         if (nTopRow != temp)
  1867.         {
  1868.             nTopRow = temp;
  1869.             VBar.setValue(temp);
  1870.             bAllDirty = true;
  1871.             if (!bInternalBlockPaint) repaint();
  1872.         }
  1873.     }
  1874.  
  1875.     /**
  1876.      * Scroll the ImageListBox horizontally
  1877.      * @param info either an absolute value or Event.SCROLL_PAGE_DOWN,
  1878.      * Event.SCROLL_PAGE_UP, Event.SCROLL_LINE_DOWN, Event.SCROLL_LINE_UP
  1879.      * the range for absolute value should be between 0 pixel width of ImageListBox
  1880.      * @param bAbsolute whether to treat the info as an absolute value or as one of the constants
  1881.      */
  1882.     public synchronized void scrollHorizontal(int info, boolean bAbsolute)
  1883.     {
  1884.         int temp = xCoord;
  1885.  
  1886.         if (bAbsolute)
  1887.             temp = -info;
  1888.         else
  1889.         {
  1890.             switch (info)
  1891.             {
  1892.                 case Event.SCROLL_PAGE_DOWN:    temp -= lWidth; break;
  1893.                 case Event.SCROLL_PAGE_UP:      temp += lWidth; break;
  1894.                 case Event.SCROLL_LINE_DOWN:    temp -= 1; break;
  1895.                 case Event.SCROLL_LINE_UP:      temp += 1; break;
  1896.             }
  1897.         }
  1898.  
  1899.         if (temp > 0)
  1900.             temp = 0;
  1901.         else if ( (-temp) > HBar.getMaximum())
  1902.             temp = -HBar.getMaximum();
  1903.  
  1904.         if (xCoord != temp)
  1905.         {
  1906.             xCoord = temp;
  1907.             HBar.setValue(-temp);
  1908.             bAllDirty = true;
  1909.             if (!bInternalBlockPaint) repaint();
  1910.         }
  1911.     }
  1912.  
  1913.     /**
  1914.      * Handles redrawing of this component on the screen.
  1915.      * This is a standard Java AWT method which gets called by the Java
  1916.      * AWT (repaint()) to handle repainting this component on the screen.
  1917.      * The graphics context clipping region is set to the bounding rectangle
  1918.      * of this component and its <0,0> coordinate is this component's 
  1919.      * top-left corner.
  1920.      * Typically this method paints the background color to clear the
  1921.      * component's drawing space, sets graphics context to be the foreground
  1922.      * color, and then calls paint() to draw the component.
  1923.      *
  1924.      * It is overridden here to allow the blocking of painting.
  1925.      *
  1926.      * @param g the graphics context
  1927.      * @see java.awt.Component#repaint
  1928.      * @see #paint
  1929.      */
  1930.     public synchronized void update(Graphics g)
  1931.     {
  1932.         if (!bBlockPaint && !bInternalBlockPaint)
  1933.             paint(g);
  1934.     }
  1935.  
  1936.     /**
  1937.      * Paints this component using the given graphics context.
  1938.      * This is a standard Java AWT method which typically gets called
  1939.      * by the AWT to handle painting this component. It paints this component
  1940.      * using the given graphics context. The graphics context clipping region
  1941.      * is set to the bounding rectangle of this component and its <0,0>
  1942.      * coordinate is this component's top-left corner.
  1943.      * 
  1944.      * @param g the graphics context used for painting
  1945.      * @see java.awt.Component#repaint
  1946.      * @see #update
  1947.      */
  1948.     public synchronized void paint(Graphics g)
  1949.     {
  1950.         ListItem item;
  1951.  
  1952.         int nItems;
  1953.         int xSelectStartLoc;
  1954.         int i, j, rows;
  1955.         int vWid = 0;
  1956.         int hHt = 0;
  1957.         int gridAdj = 0;
  1958.         int yLoc = 0;
  1959.         int ySLoc = 0;
  1960.         boolean bShowV = false;
  1961.         boolean bShowH = false;
  1962.  
  1963.         // Size size of ListBox
  1964.         Rectangle rect = bounds();
  1965.         font = g.getFont();
  1966.         fm = g.getFontMetrics(font);
  1967.         fontHeight = fm.getHeight();
  1968.         fontDescent = fm.getDescent();
  1969.  
  1970.         nItems = items.size();
  1971.  
  1972.         if (bCellBorders)
  1973.             cellHt = fontHeight+5;
  1974.         else
  1975.             cellHt = fontHeight+1;
  1976.  
  1977.         if (nItems == 0)
  1978.         {
  1979.             nTopRow = 0;
  1980.             visibleRows = 0;
  1981.             bShowH = false;
  1982.             bShowV = false;
  1983.             xCoord = 0;
  1984.         }
  1985.         else
  1986.         {
  1987.             if ( bAllowShowHBar && (longestLineValue > (rect.width - borderWidth)) )
  1988.             {
  1989.                 bShowH = true;
  1990.                 hHt = barSize;
  1991.             }
  1992.             else
  1993.             {
  1994.                 bShowH = false;
  1995.                 hHt = 0;
  1996.             }
  1997.  
  1998.             rows = (rect.height - hHt - borderWidth - 4) / cellHt;
  1999.  
  2000.             if ( bAllowShowVBar && (nItems > rows) )
  2001.             {
  2002.                 bShowV = true;
  2003.                 vWid = barSize;
  2004.                 if (!bShowH)
  2005.                 {
  2006.                     if ( bAllowShowHBar && (longestLineValue > (rect.width - borderWidth - vWid)) )
  2007.                     {
  2008.                         bShowH = true;
  2009.                         hHt = barSize;
  2010.                         rows = (rect.height - hHt - borderWidth - 4) / cellHt;
  2011.                     }
  2012.                 }
  2013.             }
  2014.             else
  2015.             {
  2016.                 bShowV = false;
  2017.                 vWid = 0;
  2018.             }
  2019.  
  2020.             if (visibleRows != rows)
  2021.             {
  2022.                 visibleRows = rows;
  2023.                 bAllDirty = true;
  2024.             }
  2025.  
  2026.             if (bShowV)
  2027.             {
  2028.                 VBar.reshape(rect.width-barSize-halfBorderWidth, halfBorderWidth, barSize, rect.height-borderWidth-hHt);
  2029.                 VBar.setValues(nTopRow, visibleRows, 0, nItems - visibleRows);
  2030.                 VBar.setPageIncrement(visibleRows);
  2031.                 lWidth = rect.width-vWid-borderWidth;
  2032.  
  2033.                 if (!bVBarVisible)
  2034.                 {
  2035.                     bVBarVisible = true;
  2036.                     VBar.show();
  2037.                 }
  2038.             }
  2039.             else
  2040.             {
  2041.                 lWidth = rect.width - borderWidth;
  2042.  
  2043.                 if (bVBarVisible)
  2044.                 {
  2045.                     bVBarVisible = false;
  2046.                     VBar.hide();
  2047.                 }
  2048.             }
  2049.  
  2050.             if (bShowH)
  2051.             {
  2052.                 HBar.reshape(halfBorderWidth, rect.height-barSize-halfBorderWidth, rect.width-borderWidth-vWid, barSize);
  2053.                 HBar.setValues(-xCoord, lWidth, 0, (longestLineValue - lWidth));
  2054.                 HBar.setPageIncrement(lWidth);
  2055.  
  2056.                 if (!bHBarVisible)
  2057.                 {
  2058.                     bHBarVisible = true;
  2059.                     HBar.show();
  2060.                 }
  2061.             }
  2062.             else
  2063.             {
  2064.                 if (bHBarVisible)
  2065.                 {
  2066.                     bHBarVisible = false;
  2067.                     HBar.hide();
  2068.                 }
  2069.             }
  2070.         }
  2071.  
  2072.         if (nItems == 0 || bAllDirty)
  2073.             g.clearRect(halfBorderWidth, halfBorderWidth, rect.width-borderWidth, rect.height-borderWidth);
  2074.  
  2075.         if (borderType == 0)
  2076.         {
  2077.             g.setColor(Color.black);
  2078.             g.drawLine(0, 0, rect.width-2, 0);
  2079.             g.drawLine(0, 0, 0, rect.height-2);
  2080.  
  2081.             g.setColor(Color.gray);
  2082.             g.drawLine(1, 1, rect.width-3, 1);
  2083.             g.drawLine(1, 1, 1, rect.height-3);
  2084.  
  2085.             g.setColor(Color.lightGray);
  2086.             g.drawLine(1, rect.height-2, rect.width-2, rect.height-2 );
  2087.             g.drawLine(rect.width-2, 1, rect.width-2, rect.height-3 );
  2088.  
  2089.             g.setColor(Color.white);
  2090.             g.drawLine(0, rect.height-1, rect.width-1, rect.height-1 );
  2091.             g.drawLine(rect.width-1, 0, rect.width-1, rect.height-1 );
  2092.         }
  2093.  
  2094.         g.clipRect(halfBorderWidth, halfBorderWidth, lWidth, rect.height-halfBorderWidth);
  2095.  
  2096.         if (nTopRow >= nItems)
  2097.             nTopRow -= visibleRows + 1;
  2098.  
  2099.         i = nTopRow;
  2100.         j = Math.min(nTopRow + visibleRows, nItems);
  2101.  
  2102.         for (int dp = 0; i < j; ++i, ++dp)
  2103.         {
  2104.             yLoc = ( (dp) * (cellHt) ) + yAdj;
  2105.             ySLoc = ( (dp + 1) * (cellHt) ) + yAdj;
  2106.  
  2107.             item = (ListItem)items.elementAt(i);
  2108.             if (item.bDirty || bAllDirty)
  2109.             {
  2110.                 item.bDirty = false;
  2111.                 g.clearRect(halfBorderWidth, yLoc, lWidth, cellHt);
  2112.             }
  2113.  
  2114.             if (item.image != null)
  2115.                 xSelectStartLoc = halfBorderWidth + IMAGE_WIDTH + 2;
  2116.             else
  2117.                 xSelectStartLoc = halfBorderWidth;
  2118.  
  2119.             if (item.bCellBorder)
  2120.                 gridAdj = 2;
  2121.             else
  2122.                 gridAdj = 0;
  2123.  
  2124.             if (item.bSelected)
  2125.             {
  2126.                 g.drawImage(SelectImage, xCoord + xSelectStartLoc + gridAdj, yLoc, lWidth-xCoord, cellHt, this);
  2127.                 g.setColor(Color.white);
  2128.             }
  2129.             else
  2130.             {
  2131.                 if (item.bEnabled)
  2132.                 {
  2133.                     if (item.color == null)
  2134.                         g.setColor(enabledColor);
  2135.                     else
  2136.                         g.setColor(item.color);
  2137.                 }
  2138.                 else
  2139.                     g.setColor(disabledColor);
  2140.             }
  2141.  
  2142.             g.drawString(item.sText, xCoord + xSelectStartLoc + gridAdj, ySLoc-fontDescent);
  2143.  
  2144.             if (item.image != null)
  2145.                 g.drawImage(item.image, xCoord + halfBorderWidth + gridAdj + 2, yLoc+2, IMAGE_WIDTH, cellHt-3, this);
  2146.  
  2147.             if (item.bCellBorder)
  2148.             {
  2149.                 g.setColor(item.cellBorderColor);
  2150.                 g.drawRect(halfBorderWidth, yLoc, lWidth, cellHt);
  2151.             }
  2152.         }
  2153.  
  2154.         extraPaint(g, rect);
  2155.  
  2156.         bAllDirty = false;
  2157.     }
  2158.  
  2159.     /**
  2160.       * Override this method to add any special painting effects after text and images are painted
  2161.       * @param g the graphics
  2162.       * @param rect the bounding rectangle
  2163.       */
  2164.     public void extraPaint(Graphics g, Rectangle rect)
  2165.     {
  2166.     }
  2167.  
  2168.     /**
  2169.      * Makes this component visible.
  2170.      * This is a standard Java AWT method which gets called to show this
  2171.      * component. If this component was invisible due to a previous hide()
  2172.      * call it make this component visible again.
  2173.      *
  2174.      * @see java.awt.Component#hide
  2175.      */
  2176.     public synchronized void show()
  2177.     {
  2178.         bAllDirty = true;
  2179.         super.show();
  2180.     }
  2181.  
  2182.     /**
  2183.      * Moves and/or resizes this component.
  2184.      * This is a standard Java AWT method which gets called to move and/or 
  2185.      * resize this component. Components that are in containers with layout
  2186.      * managers should not call this method, but rely on the layout manager
  2187.      * instead.
  2188.      * 
  2189.      * @param x horizontal position in the parent's coordinate space
  2190.      * @param y vertical position in the parent's coordinate space
  2191.      * @param width the new width
  2192.      * @param height the new height
  2193.      */
  2194.     public synchronized void reshape(int x, int y, int width, int height)
  2195.     {
  2196.         bAllDirty = true;
  2197.         super.reshape(x, y, width, height);
  2198.     }
  2199.  
  2200.     /**
  2201.      * Set the list to be "dirty" to force a complete
  2202.      * paint on next repaint.
  2203.      */
  2204.     public synchronized void setDirty()
  2205.     {
  2206.         bAllDirty = true;
  2207.     }
  2208.  
  2209.     /**
  2210.      * Query if all rows are selected.
  2211.      * @return returns true if all rows in the ImageListBox
  2212.      * are selected
  2213.      */
  2214.     public boolean allSelected()
  2215.     {
  2216.         return (countSelected == items.size());
  2217.     }
  2218.  
  2219.     /**
  2220.      * The ImageListBox posts LIST_SELECT and ACTION_EVENT events
  2221.      * directly to a specific parent if one is specified.  If one
  2222.      * is not specified, the Event is posted directly to the parent
  2223.      * container UNLESS the bDirectNotify notify flag is set to
  2224.      * false.
  2225.      * @param bDirectNotify true to directly notify parent with
  2226.      * event, false to not directly notify
  2227.      * (post event to self so extended classes can handle it)
  2228.      */
  2229.     public void setDirectNotify(boolean bDirectNotify)
  2230.     {
  2231.         this.bDirectNotify = bDirectNotify;
  2232.     }
  2233.  
  2234.     /**
  2235.      * Determines if the given index is valid.
  2236.      * @param index a zero-relative index to check
  2237.      * @return true if the index is valid, false if not
  2238.      */
  2239.     protected boolean validIndex(int index)
  2240.     {
  2241.         if (index >= 0 && index < items.size())
  2242.             return true;
  2243.         return false;
  2244.     }
  2245.  
  2246.     /**
  2247.      * Determines if the item referred to by the given index is visible.
  2248.      * @param index the zero-relative index of the item to check
  2249.      * @return true if the item is visible, false if not
  2250.      */
  2251.     protected boolean isVisibleIndex(int index)
  2252.     {
  2253.         if (index >= nTopRow && index < (nTopRow + visibleRows))
  2254.             return true;
  2255.         return false;
  2256.     }
  2257.  
  2258.     /**
  2259.      * Returns a string representing the state of this object.
  2260.      * This is a standard Java AWT method which can be usefull for debugging.
  2261.      *
  2262.      * @return a handy string for debugging purposes
  2263.      */
  2264.     protected String paramString()
  2265.     {
  2266.         return super.paramString() + ", selected=" + getSelectedItem();
  2267.     }
  2268.  
  2269.     /**
  2270.      * Select an index in a multiple-selection-enabled ImageListBox
  2271.      * using Shift or Ctrl-Shift modifiers to mimic mouse
  2272.      * selecting with the Shift or Ctrl-Shift modifiers.
  2273.      * @param index the zero-relative position of the item to select multiple
  2274.      * @param bControl boolean indicating whether to select with
  2275.      * Ctrl modifier
  2276.      */
  2277.     protected void shiftSelect(int index, boolean bControl)
  2278.     {
  2279.         int i = 0;
  2280.         int s = 0;
  2281.         ListItem li;
  2282.  
  2283.         if (lastSelected == -1)
  2284.             select(index);
  2285.         else if (lastSelected == index)
  2286.         {
  2287.             if (!bControl)
  2288.             {
  2289.                 bInternalBlockPaint = true;
  2290.                 select(index);
  2291.                 bInternalBlockPaint = false;
  2292.             }
  2293.         }
  2294.         else if (lastSelected < index)
  2295.         {
  2296.             if ( !isEnabled(index) )
  2297.                 return;
  2298.  
  2299.             if (bControl)
  2300.             {
  2301.                 i = lastSelected + 1;
  2302.                 s = Math.min(items.size(), index + 1);
  2303.             }
  2304.             else
  2305.             {
  2306.                 i = 0;
  2307.                 s = items.size();
  2308.             }
  2309.             for (; i < s; i++)
  2310.             {
  2311.                 li = (ListItem)items.elementAt(i);
  2312.                 if (i < lastSelected || i > index)
  2313.                 {
  2314.                     if (li.bSelected)
  2315.                     {
  2316.                         li.bDirty = true;
  2317.                         li.bSelected = false;
  2318.                         countSelected--;
  2319.                     }
  2320.                 }
  2321.                 else
  2322.                 {
  2323.                     if (!li.bSelected)
  2324.                     {
  2325.                         li.bDirty = true;
  2326.                         li.bSelected = true;
  2327.                         countSelected++;
  2328.                     }
  2329.                 }
  2330.             }
  2331.         }
  2332.         else if (lastSelected > index)
  2333.         {
  2334.             if ( !isEnabled(index) )
  2335.                 return;
  2336.  
  2337.             if (bControl)
  2338.             {
  2339.                 i = index;
  2340.                 s = Math.min(items.size(), lastSelected);
  2341.             }
  2342.             else
  2343.             {
  2344.                 i = 0;
  2345.                 s = items.size();
  2346.             }
  2347.             for (i = 0; i < s; i++)
  2348.             {
  2349.                 li = (ListItem)items.elementAt(i);
  2350.                 if (i < index || i > lastSelected)
  2351.                 {
  2352.                     if (li.bSelected)
  2353.                     {
  2354.                         li.bDirty = true;
  2355.                         li.bSelected = false;
  2356.                         countSelected--;
  2357.                     }
  2358.                 }
  2359.                 else
  2360.                 {
  2361.                     if (!li.bSelected)
  2362.                     {
  2363.                         li.bDirty = true;
  2364.                         li.bSelected = true;
  2365.                         countSelected++;
  2366.                     }
  2367.                 }
  2368.             }
  2369.         }
  2370.         if (!bInternalBlockPaint) repaint();
  2371.     }
  2372.  
  2373.     /**
  2374.      * Select an index in a ImageListBox using the Ctrl modifier
  2375.      * to mimic mouse selecting with the Ctrl modifier.
  2376.      * @param index the zero-relative position of the item to select
  2377.      */
  2378.     protected void ctrlSelect(int index)
  2379.     {
  2380.         ListItem listItem = (ListItem)items.elementAt(index);
  2381.         if (!listItem.bEnabled)
  2382.             return;
  2383.  
  2384.         if (listItem.bSelected)
  2385.         {
  2386.             listItem.bSelected = false;
  2387.             countSelected--;
  2388.             lastSelected = -1;
  2389.         }
  2390.         else
  2391.         {
  2392.             listItem.bSelected = true;
  2393.             countSelected++;
  2394.             lastSelected = index;
  2395.         }
  2396.         listItem.bDirty = true;
  2397.         if (!bInternalBlockPaint) repaint();
  2398.     }
  2399.  
  2400.     /**
  2401.      * A utility routine that determines the item index the mouse is in
  2402.      * given the y coordinate of the mouse.
  2403.      * @param y mouse y coordinate
  2404.      * @return the zero-relative index of the item the mouse is in
  2405.      */
  2406.     protected int mouseCalcIndex(int y)
  2407.     {
  2408.         int mci;
  2409.  
  2410.         if (y < yAdj)
  2411.             mci = nTopRow - 1;
  2412.         else
  2413.             mci = ((y - yAdj) / cellHt) + nTopRow;
  2414.  
  2415.         if (mci >= items.size())
  2416.             mci = -1;
  2417.         else if (mci < 0)
  2418.             mci = 0;
  2419.  
  2420.         return mci;
  2421.     }
  2422.  
  2423.     private void updateWidth(ListItem li)
  2424.     {
  2425.         int lineWidth = li.lineWidth + LINE_SLOP;
  2426.         if (li.image != null)
  2427.             lineWidth += IMAGE_WIDTH;
  2428.         if ( lineWidth > longestLineValue)
  2429.             longestLineValue = lineWidth;
  2430.     }
  2431.  
  2432.     private void updateWidths(FontMetrics fm)
  2433.     {
  2434.         longestLineValue = 0;
  2435.         int s = items.size();
  2436.         int lineWidth = 0;
  2437.         ListItem li;
  2438.         for (int x = 0; x < s; x++)
  2439.         {
  2440.             li = (ListItem)items.elementAt(x);
  2441.             li.updateWidth(fm);
  2442.  
  2443.             lineWidth = li.lineWidth + LINE_SLOP;
  2444.             if (li.image != null)
  2445.                 lineWidth += IMAGE_WIDTH;
  2446.             if ( lineWidth > longestLineValue)
  2447.                 longestLineValue = lineWidth;
  2448.         }
  2449.     }
  2450.  
  2451.     private void notifyParent(Event evt, int index, boolean bDoubleClick)
  2452.     {
  2453.         Component postTo = null;
  2454.         if (ilbParent != null)
  2455.             postTo = ilbParent;
  2456.         else if (bDirectNotify)
  2457.             postTo = getParent();
  2458.  
  2459.         if (postTo == null)
  2460.             postTo = this;
  2461.  
  2462.         if (bDoubleClick)
  2463.         {
  2464.             postTo.postEvent(new Event(this, evt.when, Event.ACTION_EVENT,
  2465.                                             evt.x, evt.y, evt.key, lastDownModifiers, getSelectedItem()));
  2466.         }
  2467.         else
  2468.         {
  2469.             //inside image display area, and line has image!
  2470.             if (evt.x >= 0 && (evt.x - xCoord) < IMAGE_WIDTH)
  2471.             {
  2472.                 ListItem listItem = (ListItem)items.elementAt(index);
  2473.                 if (listItem.image != null)
  2474.                 {
  2475.                     postTo.postEvent(new Event(this, evt.when, EVT_IMAGE_SELECT,
  2476.                                                 evt.x, evt.y, evt.key, lastDownModifiers, new Integer(index)));
  2477.                 }
  2478.             }
  2479.  
  2480.             postTo.postEvent(new Event(this, evt.when, Event.LIST_SELECT,
  2481.                                         evt.x, evt.y, evt.key, lastDownModifiers, new Integer(index)));
  2482.         }
  2483.     }
  2484.  
  2485.     private int keyCalcIndex(int offset, boolean bAbsolute)
  2486.     {
  2487.         if (bAbsolute)
  2488.             lastIndex = offset;
  2489.         else
  2490.             lastIndex += offset;
  2491.  
  2492.         if (lastIndex >= items.size())
  2493.             lastIndex = items.size() - 1;
  2494.         else if (lastIndex < 0)
  2495.             lastIndex = 0;
  2496.  
  2497.         return lastIndex;
  2498.     }
  2499. }
  2500.